﻿using Contracts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CommandBus
{
    public class InProcCommandBus : ICommandBus
    {
        public InProcCommandBus()
        {
            this.commands = new Queue<ICommand>();
            this.observers = new List<IObserver<ICommand>>();
        }

        public void Add(ICommand command)
        {
            commands.Enqueue(command);
        }

        public IDisposable Subscribe(IObserver<ICommand> observer)
        {
            if (!observers.Contains(observer))
            {
                observers.Add(observer);
            }

            return new Unsubscriber(observers, observer);
        }

        private Queue<ICommand> commands;
        private List<IObserver<ICommand>> observers;

        public ICommand Last()
        {
            return commands.Peek();
        }

        private class Unsubscriber : IDisposable
        {
            public Unsubscriber(List<IObserver<ICommand>> observers, IObserver<ICommand> observer)
            {
                this.observers = observers;
                this.observer = observer;
            }

            public void Dispose()
            {
                if (observer != null && observers.Contains(observer))
                {
                    observers.Remove(observer);
                }
            }

            private List<IObserver<ICommand>> observers;
            private IObserver<ICommand> observer;
        }
    }
}
